package circle;

/**
 * @Author lichunlong lcl253137@alibaba-inc.com
 * @Desc 使用数组模拟环形队列-实现类: 通过取模的方式实现
 * @Date 2024-04-12
 */
public class CircleArrayQueueRealize {

    /**
     * 表示数组的最大容量
     */
    private int maxSize;

    /**
     * front就指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素; front的初始值=0
     */
    private int front;

    /**
     * rear队列尾指向队列的最后一个元素的后一个位置。因为希望空出一个空间做为约定; rear的初始值=0
     */
    private int rear;

    /**
     * 用于存放数据,模拟队列
     */
    private int[] arr;

    /**
     * 创建队列的构造器
     *
     * @param arrMaxSize 数组大小/队列长度
     */
    public CircleArrayQueueRealize(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
    }

    /**
     * 判断队列是否满
     *
     * @return 队列是否满的标识
     */
    public boolean isFull() {
        return (rear + 1) % maxSize == front;
    }

    /**
     * 判断队列是否为空
     *
     * @return 队列是否为空的标识
     */
    public boolean isEmpty() {
        return rear == front;
    }

    /**
     * 添加数据到队列
     *
     * @param n 要添加的数据
     */
    public void addQueue(int n) {
        // 判断队列是否满
        if (isFull()) {
            System.out.println("队列满，不能加入数据~");
            return;
        }
        // 直接将数据加入
        arr[rear] = n;

        //将rear后移,这里必须考虑取模
        rear = (rear + 1) % maxSize;
    }

    /**
     * 获取队列的数据
     *
     * @return 获取的数据
     */
    public int getQueue() {
        // 判断队列是否空
        if (isEmpty()) {
            throw new RuntimeException("队列空，不能取数据");
        }

        // 直接将数据取出
        int value = arr[front];
        // 将front后移,并考虑取模
        front = (front + 1) % maxSize;
        return value;
    }

    /**
     * 求出当前队列有效数据的个数
     *
     * @return 当前队列有效数据的个数
     */
    public int size() {
        // front = 1, rear = 2, maxSize = 3
        return (rear + maxSize - front) % maxSize;
    }

    /**
     * 遍历显示队列的所有数据
     */
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列空的，没有数据~~");
            return;
        }

        for (int i = front; i < front + size(); i++) {
            System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
        }
    }

    /**
     * 显示队列的头数据
     *
     * @return 队列的头数据
     */
    public int headQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列空的，没有数据~~");
        }

        return arr[front];
    }
}
